//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#include <windows.h>
#include <keybddr.h>
#include <LayMgr.h>
#include <DeviceLayout.h>
#include <NumPadRmp.h>

// Generated by tool built on Dec 30 2003 15:22:20
// from keyboard DLL kbdru.dll
// for input locale 00010419


// Desktop virtual keys do not always match CE virtual keys. The 
// following #defines are attempts to convert those without direct
// matches. These should be reviewed and compared with the 
// corresponding input language or device layout.
//
// Virtual keys without equivalents will need to be mapped to OEM-defined
// virtual keys in order for those keys to be used. Note however, that all
// AT scan codes listed in the device layout are not necessarily generated
// by keyboards of that specific input locale. They are often listed only
// for completeness so defining their virtual keys as 0 might not be a 
// problem.

#define VK_OEM_MINUS     VK_HYPHEN        // CE naming difference
#define VK_OEM_PLUS      VK_EQUAL         // CE naming difference
#define VK_OEM_4         VK_LBRACKET      // CE naming difference
#define VK_OEM_6         VK_RBRACKET      // CE naming difference
#define VK_OEM_1         VK_SEMICOLON     // CE naming difference
#define VK_OEM_7         VK_APOSTROPHE    // CE naming difference
#define VK_OEM_3         VK_BACKQUOTE     // CE naming difference
#define VK_OEM_5         VK_BACKSLASH     // CE naming difference
#define VK_OEM_COMMA     VK_COMMA         // CE naming difference
#define VK_OEM_PERIOD    VK_PERIOD        // CE naming difference
#define VK_OEM_2         VK_SLASH         // CE naming difference
#define VK_OEM_WSCTRL    0                // No CE equivalent
#define VK_OEM_FINISH    VK_DBE_KATAKANA  // CE naming difference
#define VK_OEM_JUMP      0                // No CE equivalent
#define VK_OEM_BACKTAB   VK_DBE_ROMAN     // CE naming difference
#define VK_OEM_AUTO      VK_DBE_SBCSCHAR  // CE naming difference
#define VK_OEM_PA3       0                // No CE equivalent
#define VK_OEM_RESET     0                // No CE equivalent
#define VK_ABNT_C1       0                // No CE equivalent
#define VK_OEM_PA1       0                // No CE equivalent
#define VK_ABNT_C2       0                // No CE equivalent
#define VK_OEM_8         VK_OFF           // CE naming difference


static const DWORD dwScToVkFirst = 0x01;
static const DWORD dwScToVkLast  = 0x84;
static UINT8 rguiScToVk[] = {
    /* 01 */  VK_F9,
    /* 02 */  0,
    /* 03 */  VK_F5,
    /* 04 */  VK_F3,
    /* 05 */  VK_F1,
    /* 06 */  VK_F2,
    /* 07 */  VK_F12,
    /* 08 */  VK_F13,
    /* 09 */  VK_F10,
    /* 0A */  VK_F8,
    /* 0B */  VK_F6,
    /* 0C */  VK_F4,
    /* 0D */  VK_TAB,
    /* 0E */  VK_OEM_3,
    /* 0F */  VK_CLEAR,
    /* 10 */  VK_F14,
    /* 11 */  VK_LMENU,
    /* 12 */  VK_LSHIFT,
    /* 13 */  0,
    /* 14 */  VK_LCONTROL,
    /* 15 */  'Q',
    /* 16 */  '1',
    /* 17 */  VK_OEM_WSCTRL,
    /* 18 */  VK_F15,
    /* 19 */  VK_OEM_RESET,
    /* 1A */  'Z',
    /* 1B */  'S',
    /* 1C */  'A',
    /* 1D */  'W',
    /* 1E */  '2',
    /* 1F */  VK_OEM_FINISH,
    /* 20 */  VK_F16,
    /* 21 */  'C',
    /* 22 */  'X',
    /* 23 */  'D',
    /* 24 */  'E',
    /* 25 */  '4',
    /* 26 */  '3',
    /* 27 */  VK_OEM_JUMP,
    /* 28 */  VK_F17,
    /* 29 */  VK_SPACE,
    /* 2A */  'V',
    /* 2B */  'F',
    /* 2C */  'T',
    /* 2D */  'R',
    /* 2E */  '5',
    /* 2F */  VK_EREOF,
    /* 30 */  VK_F18,
    /* 31 */  'N',
    /* 32 */  'B',
    /* 33 */  'H',
    /* 34 */  'G',
    /* 35 */  'Y',
    /* 36 */  '6',
    /* 37 */  VK_OEM_BACKTAB,
    /* 38 */  VK_F19,
    /* 39 */  0,
    /* 3A */  'M',
    /* 3B */  'J',
    /* 3C */  'U',
    /* 3D */  '7',
    /* 3E */  '8',
    /* 3F */  VK_OEM_AUTO,
    /* 40 */  VK_F20,
    /* 41 */  VK_OEM_COMMA,
    /* 42 */  'K',
    /* 43 */  'I',
    /* 44 */  'O',
    /* 45 */  '0',
    /* 46 */  '9',
    /* 47 */  0,
    /* 48 */  VK_F21,
    /* 49 */  VK_OEM_PERIOD,
    /* 4A */  VK_OEM_2,
    /* 4B */  'L',
    /* 4C */  VK_OEM_1,
    /* 4D */  'P',
    /* 4E */  VK_OEM_MINUS,
    /* 4F */  0,
    /* 50 */  VK_F22,
    /* 51 */  VK_ABNT_C1,
    /* 52 */  VK_OEM_7,
    /* 53 */  0,
    /* 54 */  VK_OEM_4,
    /* 55 */  VK_OEM_PLUS,
    /* 56 */  VK_ZOOM,
    /* 57 */  VK_F23,
    /* 58 */  VK_CAPITAL,
    /* 59 */  VK_RSHIFT,
    /* 5A */  VK_RETURN,
    /* 5B */  VK_OEM_6,
    /* 5C */  0,
    /* 5D */  VK_OEM_5,
    /* 5E */  VK_HELP,
    /* 5F */  VK_F24,
    /* 60 */  0,
    /* 61 */  VK_OEM_102,
    /* 62 */  0,
    /* 63 */  0,
    /* 64 */  0,
    /* 65 */  0,
    /* 66 */  VK_BACK,
    /* 67 */  VK_OEM_PA1,
    /* 68 */  VK_TAB,
    /* 69 */  VK_NUMPAD1,
    /* 6A */  0,
    /* 6B */  VK_NUMPAD4,
    /* 6C */  VK_NUMPAD7,
    /* 6D */  VK_ABNT_C2,
    /* 6E */  0,
    /* 6F */  VK_OEM_PA3,
    /* 70 */  VK_NUMPAD0,
    /* 71 */  VK_DECIMAL,
    /* 72 */  VK_NUMPAD2,
    /* 73 */  VK_NUMPAD5,
    /* 74 */  VK_NUMPAD6,
    /* 75 */  VK_NUMPAD8,
    /* 76 */  VK_ESCAPE,
    /* 77 */  VK_NUMLOCK,
    /* 78 */  VK_F11,
    /* 79 */  VK_ADD,
    /* 7A */  VK_NUMPAD3,
    /* 7B */  VK_SUBTRACT,
    /* 7C */  VK_MULTIPLY,
    /* 7D */  VK_NUMPAD9,
    /* 7E */  VK_SCROLL,
    /* 7F */  0,
    /* 80 */  0,
    /* 81 */  0,
    /* 82 */  0,
    /* 83 */  VK_F7,
    /* 84 */  VK_SNAPSHOT,
};

static ScanCodeToVKeyData scvk = {
    0x00,
    dwScToVkFirst,
    dwScToVkLast,
    rguiScToVk
};


static const DWORD dwE0ScToVkFirst = 0xE010;
static const DWORD dwE0ScToVkLast  = 0xE07E;
static UINT8 rguiE0ScToVk[] = {
    /* E010 */  VK_BROWSER_SEARCH,
    /* E011 */  VK_RMENU,
    /* E012 */  0,
    /* E013 */  0,
    /* E014 */  VK_RCONTROL,
    /* E015 */  VK_MEDIA_PREV_TRACK,
    /* E016 */  0,
    /* E017 */  0,
    /* E018 */  VK_BROWSER_FAVORITES,
    /* E019 */  0,
    /* E01A */  0,
    /* E01B */  0,
    /* E01C */  0,
    /* E01D */  0,
    /* E01E */  0,
    /* E01F */  VK_LWIN,
    /* E020 */  VK_BROWSER_REFRESH,
    /* E021 */  VK_VOLUME_DOWN,
    /* E022 */  0,
    /* E023 */  VK_VOLUME_MUTE,
    /* E024 */  0,
    /* E025 */  0,
    /* E026 */  0,
    /* E027 */  VK_RWIN,
    /* E028 */  VK_BROWSER_STOP,
    /* E029 */  0,
    /* E02A */  0,
    /* E02B */  VK_LAUNCH_APP2,
    /* E02C */  0,
    /* E02D */  0,
    /* E02E */  0,
    /* E02F */  VK_APPS,
    /* E030 */  VK_BROWSER_FORWARD,
    /* E031 */  0,
    /* E032 */  VK_VOLUME_UP,
    /* E033 */  0,
    /* E034 */  VK_MEDIA_PLAY_PAUSE,
    /* E035 */  0,
    /* E036 */  0,
    /* E037 */  0,
    /* E038 */  VK_BROWSER_BACK,
    /* E039 */  0,
    /* E03A */  VK_BROWSER_HOME,
    /* E03B */  VK_MEDIA_STOP,
    /* E03C */  0,
    /* E03D */  0,
    /* E03E */  0,
    /* E03F */  VK_OEM_8,
    /* E040 */  VK_LAUNCH_APP1,
    /* E041 */  0,
    /* E042 */  0,
    /* E043 */  0,
    /* E044 */  0,
    /* E045 */  0,
    /* E046 */  0,
    /* E047 */  0,
    /* E048 */  VK_LAUNCH_MAIL,
    /* E049 */  0,
    /* E04A */  VK_DIVIDE,
    /* E04B */  0,
    /* E04C */  0,
    /* E04D */  VK_MEDIA_NEXT_TRACK,
    /* E04E */  0,
    /* E04F */  0,
    /* E050 */  VK_LAUNCH_MEDIA_SELECT,
    /* E051 */  0,
    /* E052 */  0,
    /* E053 */  0,
    /* E054 */  0,
    /* E055 */  0,
    /* E056 */  0,
    /* E057 */  0,
    /* E058 */  0,
    /* E059 */  0,
    /* E05A */  VK_RETURN,
    /* E05B */  0,
    /* E05C */  0,
    /* E05D */  0,
    /* E05E */  0,
    /* E05F */  0,
    /* E060 */  0,
    /* E061 */  0,
    /* E062 */  0,
    /* E063 */  0,
    /* E064 */  0,
    /* E065 */  0,
    /* E066 */  0,
    /* E067 */  0,
    /* E068 */  0,
    /* E069 */  VK_END,
    /* E06A */  0,
    /* E06B */  VK_LEFT,
    /* E06C */  VK_HOME,
    /* E06D */  0,
    /* E06E */  0,
    /* E06F */  0,
    /* E070 */  VK_INSERT,
    /* E071 */  VK_DELETE,
    /* E072 */  VK_DOWN,
    /* E073 */  0,
    /* E074 */  VK_RIGHT,
    /* E075 */  VK_UP,
    /* E076 */  0,
    /* E077 */  0,
    /* E078 */  0,
    /* E079 */  0,
    /* E07A */  VK_NEXT,
    /* E07B */  0,
    /* E07C */  VK_SNAPSHOT,
    /* E07D */  VK_PRIOR,
    /* E07E */  VK_CANCEL,
};

static ScanCodeToVKeyData scvkE0 = {
    0xE000,
    dwE0ScToVkFirst,
    dwE0ScToVkLast,
    rguiE0ScToVk
};


static const DWORD dwE114ScToVkFirst = 0xE11477;
static const DWORD dwE114ScToVkLast  = 0xE11477;
static UINT8 rguiE114ScToVk[] = {
    /* E11477 */  VK_PAUSE,
};

static ScanCodeToVKeyData scvkE114 = {
    0xE11400,
    dwE114ScToVkFirst,
    dwE114ScToVkLast,
    rguiE114ScToVk
};


static ScanCodeToVKeyData *rgscvkAT[] = {
    &scvk, &scvkE0, &scvkE114
};


//-----------------------------------------------------------------------------
// Remapping function

#define IsShiftModifier(x) ((x) == VK_LSHIFT || (x) == VK_RSHIFT || \
	(x) == VK_LCONTROL || (x) == VK_RCONTROL || (x) == VK_LMENU || (x) == VK_RMENU || \
	(x) == VK_LWIN || (x) == VK_RWIN)


static
UINT
WINAPI
ATRemapVKey(
    const KEYBD_EVENT *pKbdEvents,
    UINT               cKbdEvents,
    KEYBD_EVENT       *pRmpKbdEvents,
    UINT               cMaxRmpKbdEvents
    )
{
    UINT cRmpKbdEvents;

    if (pRmpKbdEvents == NULL) {
        // 1 to 1 mapping for whatever NumPadRemapVKey returns
        ASSERT(cMaxRmpKbdEvents == 0);
        return NumPadRemapVKey(pKbdEvents, cKbdEvents, NULL, 0);
    }
    
    ASSERT(pKbdEvents != NULL);

    // We know that we will only map one input to one output. Thus, we only
    // need for NumPadRemapVKey() to check the number of input events since
    // we will not use more than it does. If the buffer is not large enough
    // cRmpKbdEvents will be 0 and we will return 0.
    cRmpKbdEvents = NumPadRemapVKey(pKbdEvents, cKbdEvents, 
        pRmpKbdEvents, cMaxRmpKbdEvents);

    for (UINT ui = 0; ui < cRmpKbdEvents; ++ui) 
    {
        if (pRmpKbdEvents[ui].KeyStateFlags & KeyStateDownFlag) {
            UINT32 vkOnly = LOBYTE(pRmpKbdEvents[ui].uiVk);

            // If the incoming key is a shift modifier of some sort, turn off keyclick autorepeat by default.
            // We will allow the shift key to click on the first press, since many keyboards don't have built-in
            // sound generators and users appreciate audible feedback when they press a key.
            if(IsShiftModifier(vkOnly) || vkOnly == VK_CAPITAL || vkOnly == VK_NUMLOCK) {
                pRmpKbdEvents[ui].uiVk |= KEYBD_DEVICE_SILENT_REPEAT;
            }
        }
    }

    return cRmpKbdEvents;
}
#ifdef DEBUG
// Verify function declaration against the typedef.
static PFN_KEYBD_REMAP g_pfnATRemapVKey = ATRemapVKey;
#endif


static DEVICE_LAYOUT dlAT =
{
    sizeof(DEVICE_LAYOUT),
    PS2_AT_PDD | PS2_NOP_PDD,
    rgscvkAT,
    dim(rgscvkAT),
    ATRemapVKey,
};


extern "C"
BOOL
PS2_AT_00010419(
    PDEVICE_LAYOUT pDeviceLayout
    )
{
    PREFAST_ASSERT(pDeviceLayout != NULL);

    BOOL fRet = FALSE;

    if (pDeviceLayout->dwSize != sizeof(DEVICE_LAYOUT)) {
        RETAILMSG(1, (_T("PS2_AT_00010419: data structure size mismatch\r\n")));
        goto leave;
    }

    // Make sure that the Sc->Vk tables are the sizes that we expect
    ASSERT(dim(rguiScToVk    ) == (1 + dwScToVkLast     - dwScToVkFirst    ));
    ASSERT(dim(rguiE0ScToVk  ) == (1 + dwE0ScToVkLast   - dwE0ScToVkFirst  ));
    ASSERT(dim(rguiE114ScToVk) == (1 + dwE114ScToVkLast - dwE114ScToVkFirst));

    *pDeviceLayout = dlAT;

    fRet = TRUE;

leave:
    return fRet;
}
#ifdef DEBUG
// Verify function declaration against the typedef.
static PFN_DEVICE_LAYOUT_ENTRY g_pfnDLEntry = PS2_AT_00010419;
#endif

